package test;

import dsa.LinkedList;
import dsa.ListIterator;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;

/**
 * 
 * @author Chris Meyers
 */
public class ChrisMeyersTest {
    
    LinkedList l;
    
    @Before
    public void setUp() {
        l = new LinkedList();
        l.addFirst("one");
        l.addFirst("two");
        l.addFirst("three");
        l.addFirst("a");
        l.addFirst("b");
        l.addFirst("c");
        l.addLast("I am last!");
    }

    @Test
    public void testSize() {
        assertTrue(l.size() == 7);
    }

    @Test
    public void testAddFirst() {
        assertTrue(l.get(0).equals("c")); //lower bound test
        assertTrue(l.get(6).equals("I am last!")); //upper bound test
    }

    @Test
    public void testAddLast() {
        assertTrue(l.get(l.size()-1).equals("I am last!"));
    }

    @Test
    public void testRemove() {
        int index = 1;
        l.remove(index);
        assertTrue(l.get(index).equals("a"));
    }

    @Test
    public void testRemoveFirst() {
        l.removeFirst();
        Object expResult = "b";
        assertTrue(l.get(0).equals(expResult));
    }

    @Test
    public void testRemoveLast() {
        l.removeLast();
        assertTrue(l.get(l.size()-1).equals("one"));
    }

    @Test
    public void testIndexOf() {
        Object data = "c";
        int expResult = 0;
        int result = l.indexOf(data);
        assertEquals(expResult, result);
    }

    @Test
    public void testGet() {
        int index = 6;
        Object expResult = "I am last!";
        Object result = l.get(index);
        assertEquals(expResult, result);
    }

    @Test
    public void testContains() {
        Object data = "a";
        boolean expResult = true;
        boolean result = l.contains(data);
        assertEquals(expResult, result);
    }

    @Test
    public void testGetFirst() {
        Object expResult = "c";
        Object result = l.getFirst();
        assertEquals(expResult, result);
    }

    @Test
    public void testGetLast() {
        Object expResult = "I am last!";
        Object result = l.getLast();
        assertEquals(expResult, result);
    }

    @Test
    public void testSet() {
        l.set(3, "apple");
        assertTrue(l.get(3).equals("apple"));
    }

    @Test
    public void testToArray() {
        Object[] array = l.toArray();
        
        Object[] expResult = new Object[7];
        expResult[0] = "c";
        expResult[1] = "b";
        expResult[2] = "a";
        expResult[3] = "three";
        expResult[4] = "two";
        expResult[5] = "one";
        expResult[6] = "I am last!";
        
        assertArrayEquals(expResult, array);
    }

    @Test
    public void testClone() {
        LinkedList result = (LinkedList)l.clone();
        for(int i = 0;i<l.size();i++){
            if(!(l.get(i).equals(result.get(i)))){
                fail("Clone is not same.");
            }
        }
    }
    /*
    @Test
    public void testEquals() {
        LinkedList list2 = new LinkedList();
        list2.addFirst("one");
        list2.addFirst("two");
        list2.addFirst("three");
        list2.addFirst("a");
        list2.addFirst("b");
        list2.addFirst("c");
        list2.addLast("I am last!");
        assertTrue(l.equals(list2));
        
        l.removeFirst();
        l.removeLast();
        list2.removeFirst();
        list2.removeLast();
        assertTrue(l.equals(list2));
        
        l.removeFirst();
        assertFalse(l.equals(list2));
    }
    */
    
    //---------------ListIterator tests---------------
    @Test
    public void testIteratorAdd() {
        ListIterator li = l.listIterator(0);
        li.add("new from iterator");
        assertEquals(l.get(0), "new from iterator");
    }
    
    @Test
    public void testIteratorHasNext() {
        ListIterator li1 = l.listIterator(0);
        assertTrue(li1.hasNext());      
        
        ListIterator li2 = l.listIterator(7);          
        assertFalse(li2.hasNext());
    }
        
    @Test
    public void testIteratorHasPervious() {
        ListIterator li = l.listIterator(0);
        assertFalse(li.hasPrevious());
        li.next();
        assertTrue(li.hasPrevious());
    }
            
    @Test
    public void testIteratorNextAndPrevious() {
        ListIterator li1 = l.listIterator(0);
        assertTrue(li1.next().equals("c"));
        
        li1.next();
        li1.next();
        assertTrue(li1.next().equals("three"));
        assertTrue(li1.previous().equals("three"));
        
        li1.next();
        li1.next();
        assertTrue(li1.next().equals("one"));
        assertTrue(li1.previous().equals("one"));
        
        li1.next();
        assertTrue(li1.next().equals("I am last!"));
    }
                
    @Test
    public void testIteratorNextIndex() {
        ListIterator li = l.listIterator(0);
        li.add("new from iterator");
        assertTrue(li.nextIndex() == 1);
    }
    
    @Test
    public void testIteratorPreviousIndex() {
        ListIterator li = l.listIterator(0);
        li.add("new from iterator");
        assertTrue(li.previousIndex() == 0);
    }
                            
    @Test
    public void testIteratorRemove() {
        ListIterator li1 = l.listIterator(1);
        li1.add("from iter");
        assertTrue(li1.next().equals("b"));
        li1.remove();
        assertTrue(li1.next().equals("a"));
    }
                                
    @Test
    public void testIteratorSet() {
        ListIterator li = l.listIterator(5);
        li.next();
        li.set("object set");
        assertTrue(l.get(5).equals("object set"));
    }
}
